home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 6 / QRZ Ham Radio Callsign Database - Volume 6.iso / mac / files / amiga / csrc720j.lzh / mbrestm.c < prev    next >
C/C++ Source or Header  |  1993-01-10  |  11KB  |  532 lines

  1. /*
  2.  *  MBRESTM - Version 1.61 - 1/20/92
  3.  *
  4.  *  Copyright (C) 1988, 1989, 1990, 1991, 1992
  5.  *  By the CBBS Group.
  6.  *
  7.  *  This program reads the individual message text files and
  8.  *  produces MAIL.DAT from the information. It is intended to
  9.  *  be used after a mail file crash of version 10.
  10.  *
  11.  *  It is expected that this program will be run from the
  12.  *  directory containing the message files. The new MAIL.DAT
  13.  *  file will also be found in this directory. It will have to
  14.  *  copied the the proper bbs directory replacing the corrupted
  15.  *  original mail file.
  16.  *
  17.  *  MBRESTM when run with any argument will complete itself without
  18.  *  any operator intervention. i.e. MBRESTM X
  19.  */
  20.  
  21. #include "mb.h"
  22. #ifndef MCH_AMIGA
  23. #include "dos.h"
  24. #else
  25. #include <libraries/dos.h>
  26. #include <exec/memory.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #endif
  30.  
  31. MAIL_HDR *mfhs;
  32. MSG_HDR *tmmhs;
  33. byte flds;
  34. char *fld[maxflds];
  35. char *cmd;
  36. char *line;
  37. char *nullstr = "";
  38.  
  39. #ifndef MCH_AMIGA
  40. char pp[44], name[1000][13], msgfile[10], badfile[10], temp[6];
  41. #else
  42. /* Quick fix for mbrestm on AMIGA. 500 is way too few messages for
  43.    any active BBS to try to recover. Our local system had just over
  44.    1000 to recover and we're not in a busy QTH! Make it 2000 for now
  45.    and hope it is big enough.
  46. */
  47. #define MAXNUM 2000
  48. char pp[44], name[MAXNUM][13], msgfile[10], badfile[10], temp[5];
  49. #endif
  50.  
  51. int count = 0;
  52. int cmp();
  53.  
  54. main(argc, argv)
  55. int argc;
  56. char *argv[];
  57. {
  58.   int x, c, y;
  59.   int xx = 1;
  60.   int recno = 1;
  61.   int msgfl, mail;
  62.   char *t;
  63.  
  64.   mfhs    =  (MAIL_HDR *) malloc(sizeof(MAIL_HDR));
  65.   tmmhs   =  (MSG_HDR *)  malloc(sizeof(MSG_HDR));
  66.   cmd     =  (char *) malloc(linelen);
  67.   line    =  (char *) malloc(linelen);
  68.  
  69.   printf("Mail Restore Program - Version 1.61\n");
  70.   if((mail = open("MAIL.DAT", O_CREAT | O_RDWR | O_BINARY, pmode)) < 0)
  71.     { puts("MAIL.DAT cannot be opened - process aborted!\n");
  72.       exit (1);
  73.     }
  74.  
  75.   dir_list();
  76.  
  77.   if (count > MAXNUM)
  78.   {
  79.     printf("Message files greater than %d. Delete some! Aborting\n",MAXNUM);
  80.     exit(1);
  81.   }
  82.   while( xx <= count)
  83.   {
  84.     y = true;
  85.     sprintf (msgfile, "%s",name[xx-1]);
  86.     printf("%s ", msgfile);
  87.     if((msgfl = open( msgfile, O_RDWR | O_BINARY)) < 0)
  88.       {
  89.    printf(" cannot be opened - bypassing this file\n");
  90.    xx++;
  91.    continue;
  92.       }
  93.  
  94.     read_rec(msgfl, 0, (char *) line);
  95.     if(!((line[253] is '\0') and (line[254] is '\r') and (line[255] is '\n')))
  96.       {
  97.    printf(" seems to be corrupted - bypassing this file\n");
  98.    close(msgfl);
  99.    sprintf(badfile, "%s.BAD", msgfile);
  100.    rename(msgfile, badfile);
  101.    xx++;
  102.    continue;
  103.       }
  104.  
  105.     fill(temp, '\0', 6);
  106.     strncpy(temp, &line[0], 5);
  107.     if (atoi(msgfile) != atoi(temp))
  108.     {
  109.       printf("OLD MSG# [%s] -> Renumbered  ", temp);
  110.       fill( &line[0], ' ', 5);
  111.       sprintf(&line[0],"%5.5s", msgfile);
  112.       line[5] = ' ';
  113.       write_rec( msgfl, 0, (char*) line);
  114.     }
  115.  
  116.     fill(tmmhs, '\0', 256);
  117.     tmmhs->rn       = xx;
  118.     tmmhs->read     = atoi( &line[61]);
  119.     tmmhs->number   = atoi( &line[0]);
  120.     tmmhs->size     = atoi( &line[9]);
  121.     tmmhs->type     = line[6];
  122.     switch (line[7])
  123.       {
  124.       case 'O': tmmhs->stat = m_stale; break;
  125.       case 'F': tmmhs->stat = m_fwd;  break;
  126.       case 'H': tmmhs->stat = m_hold; break;
  127.       case 'Y': tmmhs->stat = m_read; break;
  128.       case 'K': tmmhs->stat = m_kill; break;
  129.       case 'B': tmmhs->stat = m_busy; break;
  130.       case '$': tmmhs->stat = m_bull; break;
  131.       default:  tmmhs->stat = '\0';
  132.       }
  133.  
  134.     strncpy(tmmhs->to, &line[15], ln_call);
  135.     strncpy(tmmhs->from, &line[22], ln_call);
  136.     strncpy(tmmhs->bbs, &line[29],ln_call);
  137.     strncpy(tmmhs->date, &line[36], ln_date);
  138.     strncpy(tmmhs->time, &line[43], ln_time);
  139. #ifdef MCH_AMIGA
  140. /* Recover the lifetime */
  141.     tmmhs->lifetime = line[252];
  142. #endif
  143.     fill(tmmhs->bid, ' ', ln_bid);
  144.     if (line[48] isnt ' ') unbl(tmmhs->bid, &line[48], ln_bid);
  145.     tmmhs->ext = line[68] - '0'; 
  146.     if (tmmhs->ext is 1)
  147.     {
  148. #ifndef MCH_AMIGA
  149.       strncpy(tmmhs->flag, &line[70], mmesn);
  150. #else
  151.       strncpy((char *)tmmhs->flag, &line[70], mmesn);
  152. #endif
  153.       for( x=0, c=0; x < mmesn; x++, c++)
  154.    {
  155.    if (tmmhs->flag[x] is ' ') { tmmhs->flag[x] = '0'; c--;}
  156.    tmmhs->flag[x] = (tmmhs->flag[x]-'0');
  157.    }
  158.    tmmhs->count = c;
  159.    y = dodis();
  160.     }
  161.     if (tmmhs->ext is 2)
  162.     {
  163.       strcpy (cmd, &line[70]);
  164.       remnl (cmd);
  165.       strcpy(tmmhs->call[0], cmd);
  166.       t = strchr(&line[68], '\n');
  167.       t++;
  168.       strcpy(cmd, t);
  169.       remnl(cmd);
  170.       strcpy(tmmhs->title, cmd);
  171.     }
  172.     else
  173.     {
  174.       parse();
  175.       strcpy(tmmhs->title, fld[0]);
  176.     }
  177.     write_rec(mail,recno++,(char *)tmmhs);
  178.     close(msgfl);
  179.     if (y) puts("restored");
  180.     xx++;
  181.   }
  182.   mfhs->next    = recno;
  183.   mfhs->first   = 1;
  184.   mfhs->last    = recno-1;
  185.   mfhs->version = mb_version;
  186.   mfhs->free    = 0;
  187.   mfhs->count   = recno-1;
  188.   mfhs->unt_msg = 1;
  189.   fill(mfhs->unu, '\0', mfhsunu);
  190.   fill(mfhs->date, '\0', ln_date);
  191.   fill(mfhs->time, '\0', ln_time);
  192.   x = 1;
  193.   if (count)  x = 1 + atoi(name[count - 1]);
  194.   printf("The next message number will be %u\n", x);
  195.   *cmd = 0;
  196.   if (argc < 2)
  197.   {
  198.      printf("Enter return if OK or new message number  ");
  199.      gets(cmd);
  200.  
  201.   }
  202.   if (*cmd)  mfhs->next_msg = atoi(cmd);
  203.   else  mfhs->next_msg = x;
  204.   mfhs->unt_msg = mfhs->next_msg;
  205.   write_rec(mail, 0, (char *)mfhs);
  206.  
  207.   close(mail);
  208. }
  209.  
  210. /*
  211.  *  Parse a command line.
  212.  *
  213.  *  Input:   Line of text in line.
  214.  *  Returns: Fields are placed in cmd.
  215.  *           Fields are pointed to by fld[].
  216.  *           flds is set to the number of fields found.
  217.  *           Each field is null-terminated.
  218.  *           Fields beyond maxflds are ignored.
  219.  */
  220.  
  221. parse()
  222. {
  223.   char skip;
  224.   register short bl;
  225.   register char *in, *out;
  226.  
  227.   for (flds = 0; flds < maxflds;)
  228.     fld[flds++] = nullstr;
  229.  
  230.   in  = &line[86];
  231.   out = cmd;
  232.   bl  = false;
  233.   flds = 0;
  234.   skip = true;
  235.  
  236.   while (*in and (flds < maxflds) and (out < (cmd + linelen - 1)))
  237.   {
  238. #ifndef MCH_AMIGA
  239.     if (*in is '\r') { *in++; continue;}
  240. #else
  241. /* Work around a bug in MANX 5.0d compiler (and what a bug!)
  242.     The *in++ does not increment in, so as soon as the program finds
  243.     a '\r' it hangs in an infinite loop!
  244. */
  245.     if (*in is '\r') { in++; continue;}
  246. #endif
  247.     if (*in is '\n')  skip = !(skip);
  248.     *out = *in;
  249.     if (bl) {if ((*in <= ' ') and (skip)) { bl = false; *out = '\0'; } out++; }
  250.     else    {if (*in > ' ')  { bl = true; fld[flds++] = out++; }}
  251.     in++;
  252.   }
  253.   *out = '\0';
  254. }
  255.  
  256.  
  257. /*
  258.  *  Remove new line  and carriage returns from end of string.
  259.  */
  260.  
  261. remnl(p)
  262. char *p;
  263. {
  264.   for (; *p; p++)
  265.   {
  266.     if ((*p is '\n') or (*p is '\r')) { *p = '\0'; return; }
  267.   }
  268. }
  269. /*
  270.  *  Read random record.
  271.  */
  272.  
  273. read_rec(fid, rec, buffer)
  274. int fid;
  275. int rec;
  276. char buffer[];
  277. {
  278. #ifndef MCH_AMIGA
  279.   long lseek();
  280. #endif
  281.   long offs;
  282.  
  283.   offs = (long)rec * (long)RECSIZE;
  284.   lseek(fid, offs, 0);
  285.   return (read(fid, buffer, RECSIZE) is RECSIZE);
  286. }
  287.  
  288. /*
  289.  *  Write random record.
  290.  */
  291.  
  292. write_rec(fid, rec, buffer)
  293. int fid;
  294. int rec;
  295. char buffer[];
  296. {
  297. #ifndef MCH_AMIGA
  298.   long lseek();
  299. #endif
  300.   long offs;
  301.  
  302.   offs = (long)rec * (long)RECSIZE;
  303.   lseek(fid, offs, 0);
  304.   return (write(fid, buffer, RECSIZE) is RECSIZE);
  305. }
  306. /*
  307.  *  Fill some memory with a character.
  308.  */
  309.  
  310. fill(adr, ch, len)
  311. char *adr;
  312. char ch;
  313. int len;
  314. {
  315.   while (len--) *adr++ = ch;
  316. }
  317.  
  318. /*
  319.  *  Create the distribution list, if required.
  320.  */
  321.  
  322. dodis()
  323. {
  324.   register FILE *dfl;
  325.   char c;
  326.   char tmp[linelen];
  327.  
  328.   tmmhs->ext = 0;
  329.   if (*tmmhs->bbs is ' ') return;
  330.   unbl(tmp, tmmhs->bbs, ln_call);
  331.   strcat( tmp, ".DIS");
  332.  
  333.   if ((dfl = fopen( tmp, "r")) is NULL)
  334.      {
  335.      printf("restored without %s (file is not found)\n", tmp);
  336.      return false;
  337.      }
  338.   tmmhs->ext = 0x01;
  339.  
  340.   for (c = 0; (c <tmmhs->count) and (fgets( tmp, linelen, dfl) isnt NULL);
  341.     c++)
  342.     {
  343.     strupr(tmp);
  344.     pcall(tmmhs->call[c], tmp);
  345.     }
  346.   fclose(dfl);
  347.   return true;
  348. }
  349. /*
  350.  *  Copy LJSF string to C string.
  351.  */
  352.  
  353. unbl(to, from, size)
  354. char *to, *from;
  355. int size;
  356. {
  357.   while (size--)
  358.   {
  359.     if (*from <= ' ') { *to = '\0'; return; }
  360.     *to++ = *from++;
  361.   }
  362.   *to = '\0';
  363. }
  364. /*
  365.  *  Parse a callsign.
  366.  *  Blank pad the output field, remove trailing ssid from call.
  367.  *  Return the SSID.
  368. */
  369.  
  370. pcall(c, p)
  371. char *c;
  372. char *p;
  373. {
  374.   register short i;
  375.  
  376. /*
  377.  *  Blank fill the target buffer.
  378.  */
  379.  
  380.   fill (c, ' ', ln_call);
  381.  
  382. /*
  383.  *  Ignore leading spaces.
  384.  */
  385.  
  386.   while (*p and (*p is ' ')) p++;
  387.  
  388. /*
  389.  *  Copy the call from the string into the call buffer.
  390.  */
  391.  
  392.   for (i = ln_call; i and *p; i--)
  393.   {
  394.     if (*p <= ' ') return 0;
  395.     if (*p is '-') return atoi(++p);
  396.     *c++ = *p++;
  397.   }
  398.   if (*p++ is '-') return atoi(p); else return 0;
  399. }
  400.  
  401. /*
  402.  *  Read the file names from the current directory and store
  403.  *  the results in an array but exclude any name that is not
  404.  *  made up of all numbers.
  405.  *  Sort the resulting list in ascending order.
  406.  */
  407.  
  408. #ifndef MCH_AMIGA
  409. dir_list()
  410. {
  411.   int x, y;
  412.   char *file_name = "*.";
  413.  
  414.   printf("Reading directory - ");
  415.   bdos(0x1a, (unsigned)pp, 0);
  416.   if(18==bdos(0x4e, (unsigned)file_name, 0))
  417.     {
  418.       printf("No message files are found\n");
  419.       return;
  420.     }
  421.  
  422.   if (num( &pp[30])) strcpy (name[count++], &pp[30]);
  423.  
  424.   for(;;)
  425.   {
  426.     if(18==bdos(0x4f, 0, 0)) break;
  427.     if (num( &pp[30])) strcpy (name[count++], &pp[30]);
  428.   }
  429. #else
  430. /*
  431.  *  A directory item looks like this:
  432. struct FileInfoBlock {
  433.    LONG fib_DiskKey;
  434.    LONG fib_DirEntryType;
  435.    char fib_FileName[108];
  436.    LONG fib_Protection;
  437.    LONG fib_EntryType;
  438.    LONG fib_Size;
  439.    LONG fib_NumBlocks;
  440.    struct DateStamp fib_Date;
  441.    char fib_Comment[80];
  442.    char padding[36];
  443. };
  444.  */
  445.  
  446. typedef struct FileInfoBlock FCB;
  447.  
  448. static FCB *fcb = 0;
  449.  
  450. /*
  451.  *  Open directory and create list of numeric files.
  452.  */
  453. long lock;
  454. extern long Examine(),Lock(),ExNext();
  455. dir_list()
  456. {
  457.    int x, y;
  458.    long  result,Info();
  459.    fcb = (FCB *)AllocMem((long)sizeof(*fcb),MEMF_PUBLIC|MEMF_CLEAR);
  460. /*
  461.  *  Get a lock on the current directory
  462.  */
  463.    lock = Lock((UBYTE *)"",ACCESS_READ);
  464.    if(lock == 0L) {
  465.       return;
  466.    }
  467.    /* and examine it to make sure it's OK */
  468.    if((result = Examine(lock,fcb)) == 0L) {
  469.       UnLock(lock);
  470.       return;
  471.    }
  472.    for(;;) {
  473.       /* Get next directory entry */
  474.       if(ExNext(lock,fcb) == 0L) {
  475.          UnLock(lock);
  476.          break;
  477.       }
  478.       /* If the entry is a directory, go back for another */
  479.       if(fcb->fib_DirEntryType > 0)continue;
  480.       /* If the filename is numeric then add it into the list */
  481.       if(num(fcb->fib_FileName)) {
  482.          strcpy (name[count++], &fcb->fib_FileName[0]);
  483.          if(count >= MAXNUM) {
  484.             printf("Sorry - I can't handle more than %d entries\n",MAXNUM);
  485.             printf("Try deleting some of the older message numbers\n");
  486.             printf("manually and then try mbrestm again\n");
  487.             UnLock(lock);
  488.             FreeMem(fcb,(long)sizeof(*fcb));
  489.             exit(1);
  490.          }
  491.       }
  492.    }
  493.    FreeMem(fcb,(long)sizeof(*fcb));
  494. #endif
  495.   printf("There are %d message files\n", count);
  496.   if (count)
  497.     {
  498.       printf("***Sorting***\n");
  499.       qsort (name, count, 13, cmp);
  500.       for(x=0, y=1; x< count; x++, y++) 
  501.       {
  502.    printf("%6s", name[x]);
  503.    if(y is 10) { printf("\n"); y=0; }
  504.       }
  505.       printf("\n");
  506.     }
  507. }
  508.  
  509. /*
  510.  *  Compare two strings converted to integers.
  511.  */
  512.  
  513. int cmp(n1,n2)
  514. char *n1;
  515. char *n2;
  516. {
  517.    return (atoi(n1) - atoi(n2));
  518.  
  519. }
  520.  
  521. /*
  522.  *  Is the string a number?
  523.  */
  524.  
  525. num(p)
  526. char *p;
  527. {
  528.   for (; *p; p++) if (!isdigit(*p)) return false;
  529.   return true;
  530. }
  531.  
  532.